//
// See the file COPYING for redistribution information.
//

#include <config.h>
#include <cstring>
#include <Naipax/Common.hpp>
#include <Naipax/Error.hpp>
#include <Naipax/Digest.hpp>
#include <Naipax/History.hpp>

#include <iostream>

using namespace std;
using namespace Naipax;

History::History(const char *pFilename, uint32_t CacheSize) {
    if (pFilename == NULL) {
        NAIPAX_THROW(Error::INVALID_ARGUMENT);
    }

    try {
        _mpDb = new Db(NULL, 0);
        if (_mpDb->set_cachesize(0, CacheSize, 0) != 0) {
            NAIPAX_THROW(Error::CANNOT_OPEN_DB);
        }
        if (_mpDb->open(NULL, pFilename,
                        NULL, DB_BTREE, DB_CREATE, 0644) != 0) {
            NAIPAX_THROW(Error::CANNOT_OPEN_DB);
        }
    }
    catch (std::bad_alloc &E) {
        NAIPAX_THROW(Error::CANNOT_INIT_HISTORY);
    }
}

History::~History() {
    if (_mpDb->close(0) != 0) {
        NAIPAX_THROW(Error::CANNOT_CLOSE_DB);
    }
    delete _mpDb;
}

void History::Add(const string &rData, time_t Timeout) {
    char Digest[DIGEST_SIZE];
    Digest::Make(rData, Digest);

    Dbt Key(Digest, DIGEST_SIZE);
    time_t ExpireTime = time(NULL) + Timeout;
    Dbt Data(&ExpireTime, sizeof(ExpireTime));

    if (_mpDb->put(NULL, &Key, &Data, 0) != 0) {
        NAIPAX_THROW(Error::CANNOT_PUT_DATA);
    }
}

bool History::Has(const string &rData) {
    char Digest[DIGEST_SIZE];
    Digest::Make(rData, Digest);

    Dbt Key(Digest, DIGEST_SIZE);
    Dbt Data;
    if (_mpDb->get(NULL, &Key, &Data, 0) != 0) {
        return false;
    }

    // if it exists, then check the timeout value.
    time_t* pExpireTime = (time_t*) Data.get_data();
    // Outdated data is viewed as non-existent.
    if (time(NULL) > *pExpireTime) {
        return false;
    }

    return true;
}
